# Copyright (c) 2023-2024, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

version: '3.5'

services:

  etcd:
    restart: always
    container_name: milvus-etcd
    image: quay.io/coreos/etcd:v3.5.5
    environment:
      - ETCD_AUTO_COMPACTION_MODE=revision
      - ETCD_AUTO_COMPACTION_RETENTION=1000
      - ETCD_QUOTA_BACKEND_BYTES=4294967296
      - ETCD_SNAPSHOT_COUNT=50000
    volumes:
      - ./docker/volumes/etcd:/etcd
    command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
    healthcheck:
      test: ["CMD", "etcdctl", "endpoint", "health"]
      interval: 30s
      timeout: 20s
      retries: 3
    networks:
      - default

  minio:
    restart: always
    container_name: milvus-minio
    image: minio/minio:RELEASE.2023-03-20T20-16-18Z
    environment:
      MINIO_ACCESS_KEY: minioadmin
      MINIO_SECRET_KEY: minioadmin
    ports:
      - "9001:9001"
      - "9000:9000"
    volumes:
      - ./docker/volumes/minio:/minio_data
    command: minio server /minio_data --console-address ":9001"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3
    networks:
      - default      

  standalone:
    restart: always
    container_name: milvus-standalone
    image: milvusdb/milvus:v2.3.5
    command: ["milvus", "run", "standalone"]
    hostname: milvus
    security_opt:
    - seccomp:unconfined
    environment:
      ETCD_ENDPOINTS: etcd:2379
      MINIO_ADDRESS: minio:9000
    volumes:
      - ./docker/volumes/milvus:/var/lib/milvus
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
      interval: 30s
      start_period: 90s
      timeout: 20s
      retries: 3
    ports:
      - "19530:19530"
      - "9091:9091"
    depends_on:
      - "etcd"
      - "minio"
    networks:
      - default      

  attu:
    restart: always
    image: zilliz/attu:v2.3.5
    container_name: attu
    hostname: attu
    build:
      context: ./docker/attu
      dockerfile: Dockerfile
    environment:
      MILVUS_URL: http://milvus:19530      
    ports:
      - "3000:3000"
    networks:
      - default
      
  zookeeper:
    image: confluentinc/cp-zookeeper:7.3.2
    hostname: zookeeper
    container_name: zookeeper
    ports:
      - "2181:2181"
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_SERVER_ID: 1
      ZOOKEEPER_SERVERS: zookeeper:2888:3888
    networks:
      - default

  kafka:
    restart: always
    image: confluentinc/cp-kafka:7.3.2
    hostname: kafka
    container_name: kafka
    ports:
      - "9092:9092"
      - "29092:29092"
      - "9999:9999"
    environment:
      KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:19092,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092,DOCKER://host.docker.internal:29092
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,DOCKER:PLAINTEXT
      KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
      KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181"
      KAFKA_BROKER_ID: 1
      KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO"
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_JMX_PORT: 9999
      KAFKA_JMX_HOSTNAME: ${DOCKER_HOST_IP:-127.0.0.1}
      KAFKA_AUTHORIZER_CLASS_NAME: kafka.security.authorizer.AclAuthorizer
      KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true"
    depends_on:
      - zookeeper
    networks:
      - default

  init-kafka:
    image: confluentinc/cp-kafka:7.3.2
    depends_on:
      - kafka
    container_name: init-kafka
    entrypoint: [ '/bin/sh', '-c' ]
    command: |
      "
      # blocks until kafka is reachable
      kafka-topics --bootstrap-server kafka:19092 --list

      echo -e 'Creating kafka topics'
      kafka-topics --bootstrap-server kafka:19092 --create --if-not-exists --topic scrape_queue --replication-factor 1 --partitions 10
      kafka-topics --bootstrap-server kafka:19092 --create --if-not-exists --topic raw_queue --replication-factor 1 --partitions 10

      echo -e 'Successfully created the following topics:'
      kafka-topics --bootstrap-server kafka:19092 --list      
      "
    networks:
     - default

  streaming-ingest-dev:
    restart: always
    depends_on:
      - kafka    
    build:
      context: ./docker
      dockerfile: Dockerfile.morpheus
      target: jupyter
      args:
        - MORPHEUS_CONTAINER=${MORPHEUS_CONTAINER:-nvcr.io/nvidia/morpheus/morpheus}
        - MORPHEUS_CONTAINER_VERSION=${MORPHEUS_CONTAINER_VERSION:-24.03-runtime}
    deploy:
      resources:
        reservations:
          devices:
          - driver: nvidia
            device_ids: ['0']
            capabilities: [gpu]
    image: streaming_ingest_morpheus_jupyter    
    container_name: streaming-ingest-dev
    ports:
      - "8888:8888"
    networks:
      - default
    command: jupyter-lab --allow-root --ip=0.0.0.0 --port=8888 --no-browser --NotebookApp.token=''
    volumes:
      - ./docker/morpheus/models:/workspace/models
      - ./docker/morpheus/examples:/workspace/examples
      - ./morpheus_examples/streaming_ingest_rag:/workspace/examples/streaming_ingest_rag
    cap_add:
      - sys_nice 
    
  ingest-worker:
    restart: always
    depends_on:
      init-kafka:
        condition: service_started
      standalone:
        condition: service_healthy      
    build:
      context: ./docker
      dockerfile: Dockerfile.morpheus
      target: runtime
      args:
        - MORPHEUS_CONTAINER=${MORPHEUS_CONTAINER:-nvcr.io/nvidia/morpheus/morpheus}
        - MORPHEUS_CONTAINER_VERSION=${MORPHEUS_CONTAINER_VERSION:-24.03-runtime}
    image: streaming_ingest_morpheus
    stdin_open: true
    tty: true 
    deploy:
      resources:
        reservations:
          devices:
          - driver: nvidia
            device_ids: ['0']
            capabilities: [gpu]
    networks:
      - default
    environment:
      TERM: "${TERM:-}"
    command: python examples/llm/main.py vdb_upload pipeline --vdb_config_path "examples/llm/vdb_upload/kafka_config.yaml"
    volumes:
      - ./docker/morpheus/models:/workspace/models
      - ./docker/morpheus/examples:/workspace/examples
      - ./morpheus_examples/streaming_ingest_rag/vdb_upload:/workspace/examples/llm/vdb_upload
    cap_add:
      - sys_nice  

  producer:
    build:
      context: ../..
      dockerfile: ./experimental/streaming_ingest_rag/docker/Dockerfile.producer
    depends_on:
      - init-kafka   
      - kafka
    container_name: producer
    image: streaming_ingest_producer
    stdin_open: true
    tty: true     
    environment:
      TERM: "${TERM:-}"
      N_KAFKA_TOPIC_PARTITIONS: 10 
    networks:
      - default

  triton:
    restart: always
    image: nvcr.io/nvidia/tritonserver:23.11-py3
    container_name: triton
    hostname: triton
    ports:
      - "8000:8000"
      - "8001:8001"
      - "8002:8002"
    volumes:
      - ./docker/morpheus/models:/models
    command: [
      "tritonserver", 
      "--model-repository=/models/triton-model-repo",
      "--exit-on-error=false",
      "--log-info=true",
      "--strict-readiness=false",
      "--disable-auto-complete-config",
      "--model-control-mode=explicit",
      "--load-model",
      "all-MiniLM-L6-v2",
      ]
    deploy:
      resources:
        reservations:
          devices:
          - driver: nvidia
            device_ids: ['0']
            capabilities: [gpu]
    healthcheck:
      test: ["CMD", "curl", "-f", "localhost:8000/v2/health/ready"]
      interval: 30s
      timeout: 20s
      retries: 3
    networks:
      - default

networks:
  default:
    name: streaming-ingest
